home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zip.zip / ZIPUP.C < prev   
C/C++ Source or Header  |  1992-09-22  |  10KB  |  425 lines

  1. /*
  2.  
  3.  Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  4.  Permission is granted to any individual or institution to use, copy, or
  5.  redistribute this software so long as all of the original files are included
  6.  unmodified, that it is not sold for profit, and that this copyright notice
  7.  is retained.
  8.  
  9. */
  10.  
  11. /*
  12.  *  zipup.c by Mark Adler.
  13.  */
  14.  
  15. #define NOCPYRT         /* this is not a main module */
  16. #include "zip.h"
  17. #include "revision.h"
  18.  
  19. /* Use the raw functions for MSDOS and Unix to save on buffer space.
  20.    They're not used for VMS since it doesn't work (raw is weird on VMS).
  21.    (This sort of stuff belongs in fileio.c, but oh well.) */
  22. #ifdef VMS
  23.    typedef FILE *ftype;
  24. #  define fhow FOPR
  25. #  define fbad NULL
  26. #  define zopen(n,p) fopen(n,p)
  27. #  define zread(f,b,n) fread(b,1,n,f)
  28. #  define zclose(f) fclose(f)
  29. #  define zerr(f) ferror(f)
  30. #  define zrew(f) rewind(f)
  31. #else /* !VMS */
  32. #  ifdef MSDOS
  33. #    include <io.h>
  34. #    include <fcntl.h>
  35. #    define fhow (O_RDONLY|O_BINARY)
  36. #  else /* !MSDOS */
  37.      int open OF((char *, int));
  38.      int read OF((int, char *, int));
  39.      int close OF((int));
  40.      int lseek OF((int,long,int));
  41. #    define fhow 0
  42. #  endif /* ?MSDOS */
  43.    typedef int ftype;
  44. #  define fbad (-1)
  45. #  define zopen(n,p) open(n,p)
  46. #  define zread(f,b,n) read(f,b,n)
  47. #  define zclose(f) close(f)
  48. #  define zerr(f) (k<0)
  49. #  define zrew(f) lseek(f,0L,0)
  50. #endif /* ?VMS */
  51.  
  52.  
  53. /* Local functions */
  54. #ifdef PROTO
  55. #  ifndef UTIL
  56.      local int suffixes(char *, char *);
  57. #  endif /* !UTIL */
  58. #endif /* PROTO */
  59.  
  60.  
  61. /* Note: a zip "entry" includes a local header (which includes the file
  62.    name), an encryption header if encrypting, and the compressed data. */
  63.  
  64.  
  65. int zipcopy(z, x, y)
  66. struct zlist far *z;    /* zip entry to copy */
  67. FILE *x, *y;            /* source and destination files */
  68. /* Copy the zip entry described by *z from file *x to file *y.  Return an
  69.    error code in the ZE_ class.  */
  70. {
  71.   ulg n;                /* holds local header offset */
  72.  
  73.   if (fseek(x, z->off, SEEK_SET))
  74.     return ferror(x) ? ZE_READ : ZE_EOF;
  75.   if ((n = ftell(y)) == -1L)
  76.     return ZE_TEMP;
  77.   z->off = n;
  78.   n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
  79.   return fcopy(x, y, n);
  80. }
  81.  
  82.  
  83. #ifndef UTIL
  84.  
  85. int percent(n, m)
  86. ulg n, m;               /* n is the original size, m is the new size */
  87. /* Return the percentage compression from n to m using only integer
  88.    operations */
  89. {
  90.   if (n > 0xffffffL)            /* If n >= 16M */
  91.   {                             /*  then divide n and m by 256 */
  92.     n += 0x80;  n >>= 8;
  93.     m += 0x80;  m >>= 8;
  94.   }
  95.   return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
  96. }
  97.  
  98.  
  99. local int suffixes(a, s)
  100. char *a;                /* name to check suffix of */
  101. char *s;                /* list of suffixes separated by : or ; */
  102. /* Return true if a ends in any of the suffixes in the list s. */
  103. {
  104.   int m;                /* true if suffix matches so far */
  105.   char *p;              /* pointer into special */
  106.   char *q;              /* pointer into name a */
  107.  
  108.   m = 1;
  109.   q = a + strlen(a) - 1;
  110.   for (p = s + strlen(s) - 1; p >= s; p--)
  111.     if (*p == ':' || *p == ';')
  112.       if (m)
  113.         return 1;
  114.       else
  115.       {
  116.         m = 1;
  117.         q = a + strlen(a) - 1;
  118.       }
  119.     else
  120. #ifdef OS2
  121.     {
  122.       m = m && q >= a && tolower(*p) == tolower(*q);
  123.       q--;
  124.     }
  125. #else /* !OS2 */
  126.       m = m && q >= a && *p == *q--;
  127. #endif /* ?OS2 */
  128.   return m;
  129. }
  130.  
  131.  
  132. int zipup(z, y)
  133. struct zlist far *z;    /* zip entry to compress */
  134. FILE *y;                /* output file */
  135. /* Compress the file z->name into the zip entry described by *z and write
  136.    it to the file *y.  Determine the best method (store, shrink, or implode)
  137.    and use it.  Encrypt if requested.  Return an error code in the
  138.    ZE_ class. */
  139. {
  140.   ulg a;                /* attributes returned by filetime() */
  141.   char *b;              /* malloc'ed file buffer */
  142.   ulg c;                /* crc on uncompressed file data */
  143.   ftype f;              /* file to compress */
  144.   uch g;                /* flags returned by implode */
  145.   int h;                /* compression method chosen (how) */
  146. #ifndef NOIMPLODE
  147.   ulg i;                /* size of imploded data */
  148. #endif /* !NOIMPLODE */
  149.   extent k;             /* result of zread */
  150.   int l;                /* true if this file is a symbolic link */
  151.   int m;                /* method for this entry */
  152.   ulg n;                /* size of uncompressed file */
  153.   long q;               /* size returned by filetime */
  154.   int r;                /* temporary variable */
  155.   ulg s;                /* size of shrunk or compressed data */
  156.  
  157.   /* Open file to zip up */
  158.   if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
  159.     return ZE_OPEN;
  160.   l = issymlnk(a);
  161.   if (l)
  162.     f = fbad;
  163.   else if ((f = zopen(z->name, fhow)) == fbad)
  164.     return ZE_OPEN;
  165.  
  166.   /* Select method based on the suffix and the global method */
  167.   m = special != NULL && suffixes(z->name, special) ? STORE : method;
  168.  
  169.   /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
  170.      number used here must be <= BSZ) */
  171.   if (m == BEST && q > 512)
  172.     m = IMPLODE;
  173.   if (q == 0)
  174.     m = STORE;
  175.  
  176.   /* Make first pass on the file, computing the crc and length, and running
  177.      shrink and implode on it. */
  178.   n = 0;
  179.   c = updcrc((char *)NULL, 0);
  180.   if ((b = malloc(BSZ)) == NULL)
  181.     return ZE_MEM;
  182.   if (m == BEST || m == SHRINK)
  183.     if ((r = shr_setup()) != ZE_OK)
  184.       return r;
  185.     else
  186.       shract = 1;
  187.   while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  188.   {
  189.     n += k;
  190.     c = updcrc(b, k);
  191. #ifdef MINIX
  192.     if (l)
  193.       q = k;
  194. #endif /* MINIX */
  195.     if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
  196.     {
  197.       free((voidp *)b);
  198.       shr_clear();
  199.       shract = 0;
  200.       return r;
  201.     }
  202.     if (m == BEST)              /* free up shrink data structures */
  203.     {
  204.       if ((!l && zread(f, b, BSZ) != 0)
  205. #ifndef VMS
  206.           || n != (ulg)q
  207. #endif /* !VMS */
  208.          )
  209.         return ZE_READ;
  210.       if ((r = shr_size(&s)) != ZE_OK)
  211.       {
  212.         shr_clear();
  213.         shract = 0;
  214.         return r;
  215.       }
  216.     }
  217. #ifndef NOIMPLODE
  218.     if (m == BEST || m == IMPLODE)
  219.     {
  220.       if (!impact)
  221.         if ((r = imp_setup(q, level)) != ZE_OK)
  222.           return r;
  223.         else
  224.           impact = 1;
  225.       if ((r = imp_p1(b, k)) != ZE_OK)
  226.       {
  227.         free((voidp *)b);
  228.         imp_clear();
  229.         impact = 0;
  230.         return r;
  231.       }
  232.     }
  233. #endif /* !NOIMPLODE */
  234.     if (m == BEST || l)
  235.       break;
  236.   }
  237.   free((voidp *)b);
  238.   if (!l && zerr(f))
  239.     return ZE_READ;
  240.  
  241.   /* Determine the best method to use */
  242.   g = 0;
  243.   if (noisy && verbose)
  244.     printf(" (n=%lu)", n);
  245.   if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
  246.   {
  247.     shr_clear();
  248.     shract = 0;
  249.     return r;
  250.   }
  251.   if (noisy && verbose && (m == BEST || m == SHRINK))
  252.     printf(" (s=%lu)", s);
  253. #ifndef NOIMPLODE
  254.   if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
  255.   {
  256.     imp_clear();
  257.     impact = 0;
  258.     return r;
  259.   }
  260.   if (noisy && verbose && (m == BEST || m == IMPLODE))
  261.     printf(" (i=%lu)", i);
  262.   if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
  263.   {
  264.     if (noisy)
  265.     {
  266.       printf(" (imploded %d%%)", percent(n, i));
  267.       fflush(stdout);
  268.     }
  269.     h = IMPLODE;
  270.     s = i;
  271.     if (m == BEST)
  272.     {
  273.       shr_clear();
  274.       shract = 0;
  275.     }
  276.     if (!l)
  277.       zclose(f);
  278.   }
  279.   else
  280. #endif /* !NOIMPLODE */
  281.   if ((m == BEST || m == SHRINK) && s < n)
  282.   {
  283.     if (noisy)
  284.     {
  285.       printf(" (shrunk %d%%)", percent(n, s));
  286.       fflush(stdout);
  287.     }
  288.     h = SHRINK;
  289. #ifndef NOIMPLODE
  290.     if (m == BEST)
  291.     {
  292.       imp_clear();
  293.       impact = 0;
  294.     }
  295. #endif /* !NOIMPLODE */
  296.     if (!l)
  297.       zclose(f);
  298.   }
  299.   else
  300.   {
  301.     if (noisy)
  302.     {
  303.       printf(" (stored 0%%)");
  304.       fflush(stdout);
  305.     }
  306.     h = STORE;
  307.     s = n;
  308. #ifndef NOIMPLODE
  309.     if (m == BEST || m == IMPLODE)
  310.     {
  311.       imp_clear();
  312.       impact = 0;
  313.     }
  314. #endif /* !NOIMPLODE */
  315.     if (m == BEST || m == SHRINK)
  316.     {
  317.       shr_clear();
  318.       shract = 0;
  319.     }
  320.   }
  321.  
  322. #ifndef VMS
  323.   /* Check size (but not in VMS--variable record lengths mess it up) */
  324.   if (n != (ulg)q)
  325.     return ZE_READ;
  326. #endif /* !VMS */
  327.  
  328.   /* Fill in header information and write local header to zip file */
  329. #ifdef OS2
  330.   if ( dosify < 2 )
  331.     dosify = IsFileSystemFAT(z->name);
  332. #endif /* OS2 */
  333.  
  334.   /* (Assume ext, cext, com, and zname already filled in.) */
  335.   z->vem = dosify ? 11 :                /* Made under MSDOS by PKZIP 1.1 */
  336. #ifdef VMS
  337.                     0x200 + REVISION;   /* Made under VMS by this Zip */
  338. #else /* !VMS */
  339. #ifdef OS2
  340.                     0x600 + REVISION;   /* Made under OS/2 by this Zip */
  341. #else /* !OS2 */
  342.                     0x300 + REVISION;   /* Made under Unix by this Zip */
  343. #endif /* ?OS2 */
  344. #endif /* ?VMS */
  345.   z->ver = 10;                          /* Need PKUNZIP 1.0 */
  346.   z->flg = (ush)g;
  347.   if (key != NULL)
  348.     z->flg |= 1;
  349.   z->lflg = z->flg;
  350.   z->how = h;
  351.   z->crc = c;
  352.   z->siz = s;
  353.   if (key != NULL)
  354.     z->siz += 12;
  355.   z->len = n;
  356.   z->nam = strlen(z->zname);
  357.   z->dsk = 0;
  358.   z->att = 0;                           /* Assume they're all binary */
  359.   z->atx = dosify ? a & 0xff : a;       /* Attributes from filetime() */
  360.   if ((z->off = ftell(y)) == -1L)
  361.     return ZE_WRITE;
  362.   if ((r = putlocal(z, y)) != ZE_OK)
  363.     return r;
  364.  
  365.   /* Write stored, shrunk, or imploded file to zip file */
  366. #ifndef EXPORT
  367.   if (key != NULL)
  368.     crypthead(key, z->crc, y);
  369. #endif /* !EXPORT */
  370.   n = ftell(y);                         /* Save offset for logic check */
  371. #ifndef NOIMPLODE
  372.   if (h == IMPLODE)
  373.   {
  374.     if ((r = imp_p2(y)) != ZE_OK)
  375.       return r;
  376.     imp_clear();
  377.     impact = 0;
  378.   }
  379.   else
  380. #endif /* !NOIMPLODE */
  381.   if (h == SHRINK)
  382.   {
  383.     if ((r = shr_p2(y)) != ZE_OK)
  384.       return r;
  385.     shr_clear();
  386.     shract = 0;
  387.   }
  388.   else
  389.   {
  390.     if (!l)
  391.       zrew(f);
  392.     if ((b = malloc(BSZ)) == NULL)
  393.       return ZE_MEM;
  394.     while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  395.     {
  396.       if (zfwrite(b, 1, k, y) != k)
  397.       {
  398.         free((voidp *)b);
  399.         return ZE_TEMP;
  400.       }
  401.       if (l)
  402.         break;
  403.     }
  404.     free((voidp *)b);
  405.     if (!l && zerr(f))
  406.       return ZE_READ;
  407.     if (!l)
  408.       zclose(f);
  409.   }
  410.  
  411.   /* Check length of compressed data */
  412.   if (ftell(y) != n + s)
  413.     return ZE_LOGIC;
  414.  
  415.   /* Done--clean up and leave */
  416.   if (noisy)
  417.   {
  418.     putchar('\n');
  419.     fflush(stdout);
  420.   }
  421.   return ZE_OK;
  422. }
  423.  
  424. #endif /* !UTIL */
  425.